package myJs.cps

import myJs.Implicits._
import myJs.myPkg.Select2Options
import myJs.myPkg.jquery.{$, JQuery}
import myJs.tool.Tool
import org.scalajs.dom.{Event, html}
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks.{useEffect, useState}
import slinky.core.facade.React
import slinky.web.html._

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import scala.scalajs.js.JSConverters._

/**
 * Created by yz on 21/1/2022
 */
@react object PureSelect2MulCp {

  case class Props(name: String = "", optionMap: SeqMap[String, String], hasBv: Boolean = false, formJq: JQuery = $("#form"),
                   value: js.UndefOr[List[String]] = js.undefined,
                   onChange: js.UndefOr[List[String] => Unit] = js.undefined,
                   width: String = "150px", show: Boolean = true, allowClear: Boolean = false)


  val component = FunctionalComponent[Props] { props =>

    val (value, setValue) = useState(List.empty[String])

    val selectRef = React.createRef[html.Select]

    val placeholder = "click to choose"

    def getValue = {
      props.value.map(v => v).getOrElse(value)
    }

    def onChange(vs: List[String]) = {
      props.onChange.toOption match {
        case Some(f) => f(vs)
        case None => setValue(vs)
      }
    }

    useEffect(() => {
      val y = selectRef.current
      val curJq = $(y)
      if (props.hasBv) {
        val bv = props.formJq.bv
        bv.addField(curJq)
        if (props.show) {
          bv.revalidateField(curJq)
        } else {
          bv.updateStatus(curJq, "VALID")
        }
      }

      val data = props.optionMap.map { case (id, text) =>
        js.Dictionary("id" -> id, "text" -> text)
      }.toJSArray
      val options = Select2Options(data = data, multiple = true, placeholder = placeholder,
        allowClear = props.allowClear)
      curJq.mySelect2(options)
      refreshValue
      curJq.on("select2:select select2:unselect", (e: Event) => {
        val vs = $(y).select2Val.toList
        onChange(vs)
      })
      curJq.on("select2:clear", (e: Event) => {
        val vs = $(y).select2Val.toList
        onChange(vs)
      })
      () => {
        val y = selectRef.current
        if (props.hasBv) {
          val bv = props.formJq.bv
          val curJq = $(y)
          bv.updateStatus(curJq, "VALID").removeField(curJq)
        }
      }
    }, List()
    )

    def refreshValue = {
      val y = selectRef.current
      val jq = $(y)
      jq.select2Val(getValue.toJSArray)
    }

    useEffect(() => {
      val y = selectRef.current
      val jq = $(y)
      val data = props.optionMap.map { case (id, text) =>
        js.Dictionary("id" -> id, "text" -> text)
      }.toJSArray
      val options = Select2Options(data = data, multiple = true, placeholder = placeholder,
        allowClear = props.allowClear)
      jq.mySelect2(options)

      refreshValue

      if (props.hasBv) {
        val bv = props.formJq.bv
        if (props.show) {
          bv.revalidateField(jq)
        } else {
          bv.updateStatus(jq, "VALID")
        }
      }
    }, List(props.optionMap)
    )

    useEffect(() => {
      refreshValue
    }, List(props.value)
    )

    div(style := Style(display = Tool.b2Display(props.show)),
      select(className := "form-control", name := s"${props.name}",
        style := Style(
          width = s"${props.width}"
        ), ref := selectRef,
      )
    )

  }

}
